package com.warmer.web.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.warmer.base.util.JsonHelper;
import com.warmer.web.entity.KgGraphNodeMap;
import com.warmer.web.model.ComponentContainer;
import com.warmer.web.model.DataLink;
import com.warmer.web.model.DataNode;
import com.warmer.web.request.GraphItem;
import com.warmer.web.service.KgBuildService;
import com.warmer.web.service.KgGraphNodeMapService;
import com.warmer.web.service.KgGraphNodeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class KGBuildServiceImpl implements KgBuildService {

    @Autowired
    KgGraphNodeService kgGraphNodeService;
    @Autowired
    KgGraphNodeMapService kgGraphNodeMapService;
    @Override
    public List<String> validParam(int domainId) {
        return null;
    }

    @Override
    public void direct(int domainId) {
        long startTime = System.currentTimeMillis();
        log.info("进入-->主线程方法,开始执行,开始时间：" + startTime);
        try {
            GraphItem domainModel = kgGraphNodeService.getDomainNode(domainId);
            if (domainModel == null || domainModel.getNodeList() == null || domainModel.getNodeList().size() == 0) {
                log.error("找不到配置的信息：domainId=" + domainId);
                return;
            }
            log.info("配置信息");
            ComponentContainer componentContainer = explainComponentConfig(domainModel);
            //处理起始节点
            log.info("头结点数量：" + componentContainer.getStartNodes().size());
            componentContainer.getStartNodes().forEach(node -> {
                log.info("检查头结点");
                executeComponent(node);
                componentContainer.markExecutedDone(node);
            });
            //获取除起始节点外的所有节点
            List<String> targetIds = componentContainer.getTargetIds();
            boolean isContinue = true;
            while (isContinue) {
                //处理目标节点
                targetIds.forEach(id -> {
                    //查看前置节点是否执行完毕
                    boolean isExecutable = componentContainer.isPreNodesExecuted(id);
                    if (isExecutable) {
                        //找到后置节点，执行该节点
                        DataNode node = componentContainer.getDataNodeByNodeId(id);
                        executeComponent(node);
                        componentContainer.markExecutedDone(node);
                    }
                });
                //等待所有节点执行完成，结束
                isContinue = !componentContainer.isAllExecuted();
            }
        } catch (Exception ex) {
            log.error(ex.getMessage());
        }
        long endTime = System.currentTimeMillis();
        long totalTime = (endTime - startTime) / 1000;
        log.info("结束-->主线程方法,结束时间：" + endTime + "总共花费时间：" + totalTime + " s");
    }

    /**
     * 从config中提取流程组件
     */
    private ComponentContainer explainComponentConfig(GraphItem domainModel) {
        ComponentContainer componentContainer = new ComponentContainer();
        //解析节点
        domainModel.getNodeList().forEach(n -> {

            String nodeCode = n.getNodeKey();
            String nodeName = n.getNodeName();
            List<KgGraphNodeMap> kgGraphNodeMapList = kgGraphNodeMapService.selectByDomainId(domainModel.getDomainId());
            List<KgGraphNodeMap> collect = kgGraphNodeMapList.stream().filter(m -> m.getIsPrimary().equals(1)).collect(Collectors.toList());
            Integer foreignKeyColumnId= collect.get(0).getColumnId();
            String id = String.format("%s-%s",nodeCode,foreignKeyColumnId);
            try {
                String data = JsonHelper.toJSONString(n);
                DataNode dataNode = new DataNode();
                dataNode.setNodeId(id);
                dataNode.setNodeCode(nodeCode);
                dataNode.setNodeName(nodeName);
                dataNode.setData(data);
                componentContainer.addNode(dataNode);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        });
        //解析连线
        domainModel.getLineList().forEach(m -> {
            DataLink dataLink = new DataLink();
            dataLink.setSourceId(m.getFrom());
            dataLink.setTargetId(m.getTo());
            dataLink.setRelName(m.getLabel());
            componentContainer.addLink(dataLink);
        });
        //找到起始结点及当前节点的前置后置节点id
        componentContainer.getNodes().forEach(n -> {
                    //后置节点
                    List<String> nextNodeIds = componentContainer.getDataLinkList().stream().filter(m -> m.getSourceId().equalsIgnoreCase(n.getNodeId())).map(DataLink::getTargetId).collect(Collectors.toList());
                    List<DataNode> nextNodes = componentContainer.getNodes().stream().filter(next -> nextNodeIds.contains(next.getNodeId())).collect(Collectors.toList());
                    n.setNextNodes(nextNodes);
                    //前置节点
                    List<String> prevNodeIds = componentContainer.getDataLinkList().stream().filter(m -> m.getTargetId().equalsIgnoreCase(n.getNodeId())).map(DataLink::getSourceId).collect(Collectors.toList());
                    List<DataNode> prevNodes = componentContainer.getNodes().stream().filter(next -> prevNodeIds.contains(next.getNodeId())).collect(Collectors.toList());
                    n.setPrevNodes(prevNodes);
                    //没有前置节点就是头结点
                    if (prevNodeIds.size() == 0) {
                        n.setStart(true);
                    }
                }
        );
        return componentContainer;
    }


    /**
     * 执行组件服务调用
     *
     * @param dataNode CpNode
     */
    private void executeComponent(DataNode dataNode) {

    }

    /**
     * 验证组件参数是否正确
     *
     * @param dataNode 节点信息
     * @return 错误信息
     */
    private String validComponentParam(DataNode dataNode) {
       return null;
    }

}
